package com.web.webrecive.utils;/**
 * Created with IDEA
 * author:HanLiBin
 * Date:2018/2/28
 * Time:13:31
 * version 1.0
 */



import javax.crypto.Cipher;
import java.io.*;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;

/**
 * @author HanLiBin
 * @version V1.0
 */
public class KeyUtils {
    private static String publickey="F:\\dev\\dataDto\\src\\main\\resources\\pulibic.txt";
    private static String privatekey="F:\\dev\\dataDto\\src\\main\\resources\\private.txt";
    private final static Integer MAXSIZE=265;
    public static void  createKey(){
        KeyPairGenerator keyPairGenerator;
        try {
            keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            SecureRandom secureRandom = new SecureRandom(new Date().toString().getBytes());
            keyPairGenerator.initialize(1024, secureRandom);
            KeyPair keyPair = keyPairGenerator.genKeyPair();
            byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
            FileOutputStream fos = new FileOutputStream(publickey);
            fos.write(publicKeyBytes);
            fos.close();
            byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
            fos = new FileOutputStream("F:\\dev\\dataDto\\src\\main\\resources\\private.txt");
            fos.write(privateKeyBytes);
            fos.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /**
     * 获取公钥
     * @param filename
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(String filename) throws Exception {
        File f = new File(filename);
        FileInputStream fis = new FileInputStream(f);
        DataInputStream dis = new DataInputStream(fis);
        byte[] keyBytes = new byte[(int)f.length()];
        dis.readFully(keyBytes);
        dis.close();
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePublic(spec);
    }

    /**
     * 获取私钥
     * @param filename
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String filename)throws Exception {
        File f = new File(filename);
        FileInputStream fis = new FileInputStream(f);
        DataInputStream dis = new DataInputStream(fis);
        byte[] keyBytes = new byte[(int)f.length()];
        dis.readFully(keyBytes);
        dis.close();
        PKCS8EncodedKeySpec spec =new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePrivate(spec);
    }
    public static void main(String[] args) {

        createKey();

//        String input = "!!!hello world!!!";
//        RSAPublicKey pubKey;
//        RSAPrivateKey privKey;
//        byte[] cipherText;
//        Cipher cipher;
//        try {
//            cipher = Cipher.getInstance("RSA");
//            pubKey = (RSAPublicKey) getPublicKey(publickey);
//            privKey = (RSAPrivateKey) getPrivateKey(privatekey);
//
//            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
//            cipherText = cipher.doFinal(input.getBytes());
//            //加密后的东西
//            System.out.println("cipher: " + new String(cipherText));
//            //开始解密
//            cipher.init(Cipher.DECRYPT_MODE, privKey);
//            byte[] plainText = cipher.doFinal(cipherText);
//            System.out.println("publickey: " + Base64.getEncoder().encode(cipherText));
//            System.out.println("plain : " + new String(plainText));
//        } catch (Exception e1) {
//            // TODO Auto-generated catch block
//            e1.printStackTrace();
//        }
    }


//    公钥加密(小于117字节)
    public static String encrypt(String msg){
        RSAPublicKey pubKey;
        byte[] cipherText;
        Cipher cipher;
        try {
            cipher = Cipher.getInstance("RSA");
            pubKey = (RSAPublicKey) getPublicKey(publickey);
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            cipherText = cipher.doFinal(msg.getBytes());
            //加密后的东西
            return Base64.getEncoder().encodeToString(cipherText);
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return null;
    }
    //    私钥解密(小于117字节)
    public static String decrypt(String msg) {
        RSAPrivateKey privKey;
        Cipher cipher;
        try {
            cipher = Cipher.getInstance("RSA");
            privKey = (RSAPrivateKey) getPrivateKey(privatekey);
            //开始解密
            cipher.init(Cipher.DECRYPT_MODE, privKey);
            byte[] plainText = cipher.doFinal(Base64.getDecoder().decode(msg));
            return new String(plainText);
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return null;
    }
    /****
     * 公钥加密 分段加密(大于117字节)
     * @param data  等待加密数据
     * @return   加密数据
     * @throws Exception
     */
    public static byte [] encryptByPublicKey(String  data) throws Exception{
        byte[] bytes=data.getBytes();
        //取得公钥
        PublicKey publicKey = getPublicKey(publickey);
        //对数据加密
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE,publicKey);
        int inputLen = bytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache=new byte[2048];
        for(int i = 0; inputLen - offSet > 0; offSet = i * MAXSIZE) {
            if(inputLen - offSet > MAXSIZE) {
                cache = cipher.doFinal(bytes, offSet, MAXSIZE);
            } else {
                cache = cipher.doFinal(bytes, offSet, inputLen - offSet);
            }

            out.write(cache, 0, cache.length);
            ++i;
        }
        return out.toByteArray();
    }

    /****
     * 私钥解密 分段解密(大于117字节)
//     * @param data  待解密数据
     * @throws Exception
     * @param bytes
     */
    public static byte [] decryptByPrivateKey(byte [] bytes) throws Exception{
        //取得私钥
//        byte [] bytes=data.getBytes();
        PrivateKey privateKey = getPrivateKey(privatekey);
        //对数据解密
        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE,privateKey);
        int inputLen = bytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache=new byte[2048];
        for(int i = 0; inputLen - offSet > 0; offSet = i * MAXSIZE) {
            if(inputLen - offSet > MAXSIZE) {
                cache = cipher.doFinal(bytes, offSet, MAXSIZE);
            } else {
                cache = cipher.doFinal(bytes, offSet, inputLen - offSet);
            }

            out.write(cache, 0, cache.length);
            ++i;
        }
        return out.toByteArray();
    }
}
